package client;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.*;
import java.rmi.RemoteException;
import java.util.ArrayList;

import common.*;

import javax.swing.*;


public class GameWindow extends JFrame implements GameView, 
										WindowListener, 
										ActionListener, 
										KeyListener {

	private static final long serialVersionUID = 1L;

	private JMenuBar mb;
	private JTextArea textArea;
	private ArrayList<String> messageBlock = new ArrayList<String>();
	private JPanel scorePanel;
	private JLabel rotateLabel;
	private JLabel[] playerName = new JLabel[3];
	private JLabel[] playerScore = new JLabel[3];
	
	private JMenuItem miJoin;
	private JMenuItem miDisc;
	
	private Canvas canvas;
	
	private ClientController controller;
	
	private int colorChangeOnTick;
	
	public GameWindow(ClientController controller) {
		super("Foop1GameClient");
		this.controller = controller;
		canvas = new Canvas();
		initWindow();
	}

	private void initWindow(){
		mb= new JMenuBar();
		JMenu  menu= new JMenu("Game");
		miJoin = new JMenuItem("Join Game");
		miDisc = new JMenuItem("Disconnect");
		JMenuItem miQuit = new JMenuItem("Quit");
		miJoin.setActionCommand("join");
		miJoin.addActionListener(this);
		miDisc.setActionCommand("disconnect");
		miDisc.addActionListener(this);
		setConnected(false);
		miQuit.setActionCommand("exit");
		miQuit.addActionListener(this);
		menu.add( miJoin);
		menu.add( miDisc);
		menu.add( miQuit);
		mb.add( menu);
		this.setJMenuBar( mb);
		updateSize();
		this.setVisible( true);
		addWindowListener(this);
		JPanel panel = new JPanel( new BorderLayout());
		JPanel infoPanel = new JPanel( new GridLayout( 1, 2));
		JPanel scoreRotatePanel = new JPanel( new GridLayout( 1, 2));
		JPanel rotatePanel = new JPanel();
		rotateLabel = new JLabel();
		rotatePanel.add( rotateLabel);
		scorePanel = new JPanel( new GridLayout( 3, 2));
		for( int i = 0; i < 3; i++){
			playerName[i] = new JLabel();
			playerScore[i] = new JLabel();
			scorePanel.add( playerName[i]);
			scorePanel.add( playerScore[i]);
		}
		
		textArea = new JTextArea(5, 200);
		setMessage( "------ Welcome to Pacman! ------");
		scoreRotatePanel.add( scorePanel);
		scoreRotatePanel.add( rotatePanel);
		infoPanel.add(textArea);
		infoPanel.add(scoreRotatePanel);
		panel.add( canvas, BorderLayout.CENTER);
		panel.add( infoPanel, BorderLayout.SOUTH);
		this.add( panel);
		canvas.requestFocus();
		canvas.addKeyListener(this);
	}
	
	private void setConnected(boolean connected) {
		miDisc.setEnabled(connected);
		miJoin.setEnabled(!connected);
		if (!connected) {
			setLevel(null);
			setPlayer(null);
		}
	}

	private void updateSize() {
		this.setSize( Canvas.OFFSET*3 + canvas.getPlayfieldWidth(),
					  Canvas.OFFSET*3 + canvas.getPlayfieldHeight() + 100);
	}
	
	public void windowClosed(WindowEvent e) {}
	public void windowClosing(WindowEvent e) {
		controller.shutdown();
	}
	public void windowDeiconified(WindowEvent e) {}
	public void windowIconified(WindowEvent e) {}
	public void windowOpened(WindowEvent e) {}
	public void windowActivated(WindowEvent e) { canvas.requestFocus();}
	public void windowDeactivated(WindowEvent e) {}

	public void actionPerformed(ActionEvent e) {
		String cmd= e.getActionCommand();

		if ( cmd.equals( "exit" ) )	{
			controller.shutdown();
		} else if ( cmd.equals( "join")) {
			String name = showCustomDialog(
					"Please enter your name",
					"Your name:",
					"");
			String ip = showCustomDialog(
                    "Please enter a host address",
                    "Host address:",
                    "127.0.0.1");
			if (!controller.isAttached()) {
				try {
					controller.attachServer( ip, name);
					setConnected(true);
				} catch (RemoteException e1) {
					// TODO display error message
					e1.printStackTrace();
				}
			}
		} else if ( cmd.equals("disconnect")) {
			System.out.println("user select: disconnect");
			if (controller.isAttached()) {
				try {
					controller.detachServer();
					setConnected(false);
				} catch (RemoteException e1) {
					// TODO display error message
					e1.printStackTrace();
					setConnected(false);
				}
			}
		}
		repaint();
	}

	@Override
	public void setLevel(Level level) {
		canvas.setLevel(level);
		if( level != null)
			colorChangeOnTick = level.getColorChangeOnTick();
		updateSize();
	}

	@Override
	public void setPlayer(Player[] player) {
		canvas.setPlayer(player);
	}

	public void setCoins( Boolean[][] coin){
		canvas.setCoin(coin);
	}
	
	public void setColorChangeCount( int count){
		rotateLabel.setText( "Colors change in " + (colorChangeOnTick - count));
	}
	
	public void setMessage( String message){
		if( messageBlock.size() == 0){
			messageBlock.add( message);
		}else if( !messageBlock.get( messageBlock.size()-1).equals( message)){
			textArea.setText( addMsgToMsgBlock( message));
		}
	}
	
	public void setScore( Player[] player){
		System.out.println( player[0].GetScore());
		for( int i = 0; i < player.length; i++){
			playerName[i].setText( player[i].GetName());
			playerScore[i].setText( (new Integer(player[i].GetScore())).toString());
			playerName[i].updateUI();
			playerScore[i].updateUI();
		}
	}
	/*
	 * delete first message, add lastmessage
	 * could be done nice
	 */
	private String addMsgToMsgBlock( String msg){
		if( messageBlock.size() == 4){
			for( int i = 0; i < messageBlock.size()-1; i++){
				messageBlock.set(i, messageBlock.get(i+1));
			}
			messageBlock.set( messageBlock.size()-1, msg);
		}else{
			messageBlock.add( msg);
		}
		
		String retMsg = "";
		for( String m : messageBlock){
			retMsg += m + "\n";
		}
		return retMsg;
	}
	
	@Override
	public void updateView() {
		canvas.repaint();
	}

	@Override
	public void shutdownView() {
		canvas.removeKeyListener(this);
		this.setVisible(false);
		this.dispose();
	}
	
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyPressed(KeyEvent e) {
		if (!controller.isAttached())
			return;
		
		try {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_DOWN:
				controller.playerInput(PlayerEvent.PlayerMoveDown);
				break;
			case KeyEvent.VK_UP:
				controller.playerInput(PlayerEvent.PlayerMoveUp);
				break;
			case KeyEvent.VK_LEFT:
				controller.playerInput(PlayerEvent.PlayerMoveLeft);
				break;
			case KeyEvent.VK_RIGHT:
				controller.playerInput(PlayerEvent.PlayerMoveRight);
				break;
			default:
				break;
			}
		} catch (RemoteException e1) {
			// TODO display error message
			e1.printStackTrace();
			if (!controller.isAttached()) {
				setConnected(false);
			}
		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
	}

	private String showCustomDialog( String title, String message, String preselection){
		return (String)JOptionPane.showInputDialog(
                this,
                title,
                message,
                JOptionPane.PLAIN_MESSAGE,
                null,
                null,
                preselection);
	}
}